package token

import (
	"XSSS_v2/pkg/errno"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	"time"
)

type Context struct {
	Obj      string
	Username string
}

//解析请求中的token字符串 并添加到上下文中
func ParseRequest(c *gin.Context) (*Context, error) {
	//获取请求头部
	header := c.Request.Header.Get("Authorization")

	//从配置中加载密钥
	secret := viper.GetString("jwt_secret")

	if len(header) == 0 {
		return &Context{}, errno.ErrMissingHeader
	}
	var t string

	fmt.Sscanf(header, "Bearer %s", &t)
	//解析token
	return parse(t, secret)
}
func parse(tokenString string, secret string) (*Context, error) {
	ctx := &Context{}

	//解析touken
	token, err := jwt.Parse(tokenString, SecretFunc(secret))
	// Parse error.
	if err != nil {
		fmt.Println("解析错误：", err)
		return ctx, err
		// Read the token if it's valid.
	} else if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		ctx.Obj = claims["obj"].(string)
		ctx.Username = claims["username"].(string)
		return ctx, nil
		// Other errors.
	} else {
		fmt.Println("其他错误：", err)
		return ctx, err
	}
}

func SecretFunc(secret string) jwt.Keyfunc {
	return func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, jwt.ErrSignatureInvalid
		}
		return []byte(secret), nil
	}
}

//签发token
func Sign(c Context, secret string) (tokenString string, err error) {
	if secret == "" { //使用配置文件中的secret
		secret = viper.GetString("jwt_secret")
	}
	//添加令牌内容 生成token对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"obj":      c.Obj,
		"username": c.Username,
		"nbf":      time.Now().Unix(),
		"iat":      time.Now().Unix(),
	})
	//使用密钥加密
	tokenString, err = token.SignedString([]byte(secret))
	return

}
